/*
 * UAE - The Un*x Amiga Emulator
 *
 * Pro-Wizard glue code
 *
 * Copyright 2004 Toni Wilen
 */

#include "sysconfig.h"
#include "uae.h"
#include "gui.h"
#include "win32gui.h"
#include "memory.h"
#include "custom.h"
#include "win32.h"

#ifdef PROWIZARD

    #include "moduleripper.h"

static int got, canceled;

static void mc(byte* d, uae_ptr s, int size)
{
    int i;

    for (i = 0; i < size; i++)
        d[i] = get_byte(s++);
}

    #ifdef _WIN32
static LONG WINAPI ExceptionFilter(struct _EXCEPTION_POINTERS* pExceptionPointers, DWORD ec)
{
    return EXCEPTION_EXECUTE_HANDLER;
}
    #endif

void moduleripper()
{
    int size;
    byte* buf, * p;

    size = g_curr_conf.chipmem_size;
    size += g_curr_conf.fastmem_size;
    size += g_curr_conf.slowmem_size;
    size += g_curr_conf.mbresmem_low_size;
    size += g_curr_conf.mbresmem_high_size;
    size += g_curr_conf.z3fastmem_size;
    // size += g_curr_conf.z3fastmem2_size;
    buf = p = xmalloc(byte, size);
    if (!buf)
        return;
    memcpy(p, chipmemory, g_curr_conf.chipmem_size);
    p += g_curr_conf.chipmem_size;
    mc(p, fastmem_start, g_curr_conf.fastmem_size);
    p += g_curr_conf.fastmem_size;
    mc(p, slowmem_start, g_curr_conf.slowmem_size);
    p += g_curr_conf.slowmem_size;
    mc(p, a3000lmem_start, g_curr_conf.mbresmem_low_size);
    p += g_curr_conf.mbresmem_low_size;
    mc(p, a3000hmem_start, g_curr_conf.mbresmem_high_size);
    p += g_curr_conf.mbresmem_high_size;
    mc(p, z3fastmem_start, g_curr_conf.z3fastmem_size);
    p += g_curr_conf.z3fastmem_size;
    // mc(p, z3fastmem_start + g_curr_conf.z3fastmem_size, g_curr_conf.z3fastmem2_size);
    // p += g_curr_conf.z3fastmem2_size;

    got = 0;
    canceled = 0;
    #ifdef _WIN32
    __try {
    #endif
    prowizard_search(buf, size);
    #ifdef _WIN32
}
__except(ExceptionFilter(GetExceptionInformation(), GetExceptionCode()))
{
    Logger::Write(L"prowizard scan crashed\n");
}
    #endif
    if (!got)
        notify_user(NUMSG_MODRIP_NOTFOUND);
    else if (!canceled)
        notify_user(NUMSG_MODRIP_FINISHED);
    free(buf);
}

extern "C"
{
FILE* moduleripper_fopen(const char* aname, const char* amode)
{
    TCHAR tmp2[MAX_DPATH];
    TCHAR tmp[MAX_DPATH];
    TCHAR* name, * mode;
    FILE* f;

    fetch_ripperpath(tmp, sizeof tmp);
    name = Unicode::au(aname);
    mode = Unicode::au(amode);
    _stprintf(tmp2, L"%s%s", tmp, name);
    f = _tfopen(tmp2, mode);
    free(mode);
    free(name);
    return f;
}

FILE* moduleripper2_fopen(const char* name, const char* mode, const char* aid, int addr, int size)
{
    TCHAR msg[MAX_DPATH], msg2[MAX_DPATH];
    TCHAR* id;
    int ret;

    if (canceled)
        return nullptr;
    got++;
    translate_message(NUMSG_MODRIP_SAVE, msg);
    id = Unicode::au(aid);
    _stprintf(msg2, msg, id, addr, size);
    ret = gui_message_multibutton(2, msg2);
    free(id);
    if (ret < 0)
        canceled = 1;
    if (ret < 0 || ret != 1)
        return nullptr;
    return moduleripper_fopen(name, mode);
}

void pw_write_log(const char* format, ...)
{
}
}

#else

FILE* moduleripper_fopen(const char* name, const char* mode)
{
    return nullptr;
}
FILE* moduleripper2_fopen(const char* name, const char* mode, const char* id)
{
    return nullptr;
}

#endif